package db

import (
	"database/sql"
	cmdutils "github.com/MzoroHaHa/dev-tools/backend/app/cmd-utils"
	"github.com/MzoroHaHa/dev-tools/backend/app/logger"
	_ "github.com/mattn/go-sqlite3"
	"os"
	"path"
)

var db *sql.DB
var dbFilename string
var dbError string

var dbLogger = logger.NewLogger("db")

// GetDb 获取数据库连接
func GetDb() *sql.DB {

	if db != nil {
		return db
	}
	file := cmdutils.GetDbFile()
	if len(file) == 0 {
		file = path.Join(cmdutils.GetProgramDir(), "dev-tools.db")
	}
	_, err := os.Stat(file)
	isNew := err != nil

	dbFilename = file
	_db, err := sql.Open("sqlite3", dbFilename)
	if err != nil {
		dbError = err.Error()
		dbLogger.Error("Error opening db.", "dbErr", dbError, "file", file, "err", err)
		return nil
	}
	if _db == nil {
		dbError = "_db is nil"
		dbLogger.Error("Error opening db.", "dbErr", dbError, "file", file, "err", err)
		return nil
	}
	err = _db.Ping()
	if err != nil {
		dbError = err.Error()
	}
	db = _db

	if isNew {
		err = initTables()
		if err != nil {
			dbError = err.Error()
			dbLogger.Error("Error creating tables。", "dbErr", dbError, "file", file, "err", err)
		}
	} else {
		// 检查表结构
		_, e := db.Exec("select * from nginx_info")
		if e != nil {
			e = initTables()
			if e != nil {
				dbError = e.Error()
				dbLogger.Error("Error creating tables。", "dbErr", dbError, "file", file, "err", err)
			}
		}

		_, e = db.Exec("select * from nginx_root_config")
		if e != nil {
			e = initTables()
			if e != nil {
				dbError = e.Error()
				dbLogger.Error("Error creating tables。", "dbErr", dbError, "file", file, "err", err)
			}
		}

		_, e = db.Exec("select * from nginx_http_config")
		if e != nil {
			e = initTables()
			if e != nil {
				dbError = e.Error()
				dbLogger.Error("Error creating tables。", "dbErr", dbError, "file", file, "err", err)
			}
		}
		_, e = db.Exec("select * from nginx_http_server_config")
		if e != nil {
			e = initTables()
			if e != nil {
				dbError = e.Error()
				dbLogger.Error("Error creating tables。", "dbErr", dbError, "file", file, "err", err)
			}
		}
		_, e = db.Exec("select * from nginx_http_upstream_config")
		if e != nil {
			e = initTables()
			if e != nil {
				dbError = e.Error()
				dbLogger.Error("Error creating tables。", "dbErr", dbError, "file", file, "err", err)
			}
		}
		_, e = db.Exec("select * from nginx_stream_config")
		if e != nil {
			e = initTables()
			if e != nil {
				dbError = e.Error()
				dbLogger.Error("Error creating tables。", "dbErr", dbError, "file", file, "err", err)
			}
		}
		_, e = db.Exec("select * from nginx_stream_server_config")
		if e != nil {
			e = initTables()
			if e != nil {
				dbError = e.Error()
				dbLogger.Error("Error creating tables。", "dbErr", dbError, "file", file, "err", err)
			}
		}
		_, e = db.Exec("select * from nginx_stream_upstream_config")
		if e != nil {
			e = initTables()
			if e != nil {
				dbError = e.Error()
				dbLogger.Error("Error creating tables。", "dbErr", dbError, "file", file, "err", err)
			}
		}
	}
	return db
}

func initTables() error {
	nginx := `create table nginx_info (id varchar(64) not null primary key, name varchar(64) not null, work_dir text not null, create_date datetime not null, update_date datetime not null, exec_path text not null);`
	_, e := db.Exec(nginx)
	if e != nil {
		dbLogger.Error("create nginx_info table failed", "err", e)
	}

	// 根配置
	nginxRoot := `create table nginx_root_config
(
    id              varchar(64)  not null,
    info_id         varchar(64)  not null,
    directive_code  varchar(128) not null,
    directive_value varchar(128)
);

create unique index nginx_root_config_id_uindex
    on nginx_root_config (id);

`
	_, e = db.Exec(nginxRoot)
	if e != nil {
		dbLogger.Error("create nginx_root table failed", "err", e)
	}
	// http 配置
	httpRoot := `create table nginx_http_config
(
    id              varchar(64)  not null,
    info_id         varchar(64)  not null,
    directive_code  varchar(128) not null,
    directive_value varchar(128)
);

create unique index nginx_http_config_id_uindex
    on nginx_http_config (id);
`

	_, e = db.Exec(httpRoot)
	if e != nil {
		dbLogger.Error("create nginx_http_config table failed", "err", e)
	}
	// http server
	httpServer := `create table nginx_http_server_config
(
    id             varchar(64) not null,
    config_json    text        not null,
    info_id        varchar(64)
);

create unique index nginx_http_server_config_id_uindex
    on nginx_http_server_config (id);
`

	_, e = db.Exec(httpServer)
	if e != nil {
		dbLogger.Error("create nginx_http_server_config table failed", "err", e)
	}
	// http upstream
	httpUpstream := `create table nginx_http_upstream_config
(
    id             varchar(64) not null,
    config_json    text        not null,
    info_id        varchar(64)
);

create unique index nginx_http_upstream_config_id_uindex
    on nginx_http_upstream_config (id);
`
	_, e = db.Exec(httpUpstream)
	if e != nil {
		dbLogger.Error("create nginx_http_upstream_config table failed", "err", e)
	}
	// stream 配置
	streamRoot := `create table nginx_stream_config
(
    id               varchar(64)  not null,
    info_id          varchar(64)  not null,
    directive_code   varchar(128) not null,
    directive_value  varchar(128)
);

create unique index nginx_stream_config_id_uindex
    on nginx_stream_config (id);

`
	_, e = db.Exec(streamRoot)
	if e != nil {
		dbLogger.Error("create nginx_stream_config table failed", "err", e)
	}
	// stream server
	streamServer := `create table nginx_stream_server_config
(
    id          varchar(64) not null,
    config_json text        not null,
    info_id     varchar(64)
);

create unique index nginx_stream_server_config_id_uindex
    on nginx_stream_server_config (id);
`
	_, e = db.Exec(streamServer)
	if e != nil {
		dbLogger.Error("create nginx_stream_server_config table failed", "err", e)
	}
	// stream upstream
	streamUpstream := `create table nginx_stream_upstream_config
(
    id          varchar(64) not null,
    config_json text        not null,
    info_id     varchar(64)
);

create unique index nginx_stream_upstream_config_id_uindex
    on nginx_stream_upstream_config (id);
`
	_, e = db.Exec(streamUpstream)
	if e != nil {
		dbLogger.Error("create nginx_stream_upstream_config table failed", "err", e)
	}
	return nil
}
